package imoney.server.util;

import java.util.ArrayList;

import imoney.shared.exception.NoSuchPersonException;
import imoney.shared.model.DebtManager;
import imoney.shared.model.Group;
import imoney.shared.model.MoneyTransaction;
import imoney.shared.model.Person;
import imoney.shared.model.Registreable;

import javax.jdo.annotations.IdGeneratorStrategy;
import javax.jdo.annotations.PersistenceCapable;
import javax.jdo.annotations.Persistent;
import javax.jdo.annotations.PrimaryKey;

import com.google.appengine.api.datastore.Key;

/**
 * There should be but one instance of this object in the server, as it is
 * responsible for ids consistency. Modification of this class should be done
 * in a transaction while saving a new persistent object to the database.
 * This object is instanciated at server startup, by the context listener.
 * @author Arnaud PELOQUIN
 *
 */
@PersistenceCapable
public class IDsManager {

	@PrimaryKey
	@Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
	private Key key;
	@Persistent
	private int personIndex=0;
	@Persistent
	private int groupIndex=0;
	@Persistent
	private int debtManagerIndex=0;
	@Persistent
	private int transactionIndex=1;

	// STATIC
	/**
	 * Returns the list of ids corresponding to the list of pseudo.
	 * @param pseudos : the list of pseudos
	 * @return the list of corresponding ids
	 * @throws NoSuchPersonException if one or more pseudos are not found in the database
	 */
	public static ArrayList<Integer> getIdList(ArrayList<String> pseudos) throws NoSuchPersonException {
		ArrayList<Integer> ids = new ArrayList<Integer>();
		NoSuchPersonException nspe = new NoSuchPersonException();
		for(String pseud : pseudos) {
			try {
				Person person = DataStoreManager.getPersonByPseudo(pseud);
				ids.add(person.getId());
			} catch(NullPointerException nex) {
				nspe.addPseudo(pseud);
			}
		}
		if (nspe.getPseudos().size() > 0) {
			throw nspe;
		}
		return ids;
	}

	//GETTERS --------------------------------------------- 
	/**
	 * Returns the next usable ID for <code>Person</code> object.
	 */
	public int getPersonIndex(){
		return personIndex;
	}

	/**
	 * Returns the next usable ID for <code>Group</code> object.
	 */
	public int getGroupIndex(){
		return groupIndex;
	}

	/**
	 * Returns the next usable ID for <code>MoneyTransaction</code> object.
	 */
	public int getTransactionIndex(){
		return transactionIndex;
	}

	/**
	 * Returns the next usable ID for <code>DebtManager</code> object.
	 */
	public int getDebtManagerIndex() {
		return debtManagerIndex;
	}
	public Key getKey(){
		return key;
	}


	//METHODS ----------------------------------------------
	/**
	 * Generic method that returns a new ID for the object passed in parameter. ID is just a counter that increments
	 * each time a new object is created. For the predictable scale of this project, int type should be enough to garanty identity
	 */
	public int getNextID(Registreable object){

		// As transaction are likely to be the most numerous objects, they are placed first in the series of specification test
		if(object.getClass().getSimpleName().equals(MoneyTransaction.class.getSimpleName())){
			transactionIndex++;
			return transactionIndex-1;
		}
		if(object.getClass().getSimpleName().equals(Person.class.getSimpleName())){
			personIndex++;
			return personIndex-1;
		}
		if(object.getClass().getSimpleName().equals(Group.class.getSimpleName())){
			groupIndex++;
			return groupIndex-1;
		}
		if(object.getClass().getSimpleName().equals(DebtManager.class.getSimpleName())){
			debtManagerIndex++;
			if(groupIndex != debtManagerIndex) {
				System.err.println("Current DebtManager Id "+debtManagerIndex+
						", not consistent with current group Id "+groupIndex+", should investiguate");
			}
			return debtManagerIndex-1;
		}
		return -10;
	}

	/**
	 * Returns a String containing the database id of this IDsManager, as well
	 * as the current indexes for : persons, groups and transactions.
	 */
	public String toString(){
		return "IDsManager instance : "+key+"<br/>Persons : "+personIndex+", Groups : "+groupIndex
				+", Transactions : "+transactionIndex;
	}

}







